/*
 * Copyright (c) 2013-2015 Charkey. All rights reserved.
 *
 * This software is the confidential and proprietary information of Charkey.
 * You shall not disclose such Confidential Information and shall use it only
 * in accordance with the terms of the agreements you entered into with Charkey.
 *
 * Charkey MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE SOFTWARE,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
 *
 * Charkey SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING,
 * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 */

package cn.simastudio.talos.core.filters;

import cn.simastudio.talos.common.constants.SimaConstants;
import cn.simastudio.talos.core.enums.UserStatus;
import cn.simastudio.talos.core.model.base.User;
import cn.simastudio.talos.core.service.base.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * Usage: 提取系统用户，验证用户是否合法的过滤器；同时将用户对象添加到session
 *
 * @author Charkey
 * @date 2015/5/13 12:46
 */
@SuppressWarnings({"SpringJavaAutowiringInspection"})
public class SysUserFilter extends AccessControlFilter {

    @Autowired
    private UserService userService;

    /**
     * 用户删除了后重定向的地址
     */
    private String userNotExistsUrl;

    /**
     * 用户锁定后重定向的地址
     */
    private String userBannedBlockedUrl;

    /**
     * 未知错误
     */
    private String userUnknownErrorUrl;


    /**
     * AccessControlFilter，Shiro系统拦截的路径才会
     *
     * @param request  ServletRequest
     * @param response ServletResponse
     * @return boolean
     * @throws Exception
     */
    @Override
    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
        String username = (String) SecurityUtils.getSubject().getPrincipal();
        //Sima: 注意缓存
        User currentUser = userService.getUserByUsername(username);
        //Sima: 将当前用户放到session中
        request.setAttribute(SimaConstants.System.CURRENT_USER, currentUser);
        request.setAttribute(SimaConstants.System.CURRENT_USERNAME, username);
        //Sima: Druid监控需要
        //Todo: 注意修改此处：Druid监控需要
        ((HttpServletRequest) request).getSession().setAttribute(SimaConstants.System.CURRENT_USER, currentUser);
        ((HttpServletRequest) request).getSession().setAttribute(SimaConstants.System.CURRENT_USERNAME, username);
        return true;
    }

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        User user = (User) request.getAttribute(SimaConstants.System.CURRENT_USER);
        if (user == null) {
            return true;
        }
        // 用户状态如果是2（Deleted）、3（Locked），则不允许用户登录
        if (UserStatus.Deleted.getValue().equals(user.getStatus()) || UserStatus.Locked.getValue().equals(user.getStatus())) {
            getSubject(request, response).logout();
            saveRequestAndRedirectToLogin(request, response);
            return false;
        }
        return true;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        getSubject(request, response).logout();
        saveRequestAndRedirectToLogin(request, response);
        return true;
    }

    @Override
    protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException {
        User user = (User) request.getAttribute(SimaConstants.System.CURRENT_USER);
        String url = null;
        if (UserStatus.Deleted.getValue().equals(user.getStatus())) {
            url = getUserNotExistsUrl();
        } else if (UserStatus.Locked.getValue().equals(user.getStatus())) {
            url = getUserBannedBlockedUrl();
        } else {
            url = getUserUnknownErrorUrl();
        }

        WebUtils.issueRedirect(request, response, url);
    }

    public String getUserNotExistsUrl() {
        return userNotExistsUrl;
    }

    public void setUserNotExistsUrl(String userNotExistsUrl) {
        this.userNotExistsUrl = userNotExistsUrl;
    }

    public String getUserBannedBlockedUrl() {
        return userBannedBlockedUrl;
    }

    public void setUserBannedBlockedUrl(String userBannedBlockedUrl) {
        this.userBannedBlockedUrl = userBannedBlockedUrl;
    }

    public String getUserUnknownErrorUrl() {
        return userUnknownErrorUrl;
    }

    public void setUserUnknownErrorUrl(String userUnknownErrorUrl) {
        this.userUnknownErrorUrl = userUnknownErrorUrl;
    }
}
